package mirrormonkey.util.netevent.server;

import mirrormonkey.util.netevent.server.ConnectionEventCreator;
import mirrormonkey.util.netevent.server.ServerEventManager;
import mirrormonkey.util.netevent.server.tools.MockConnectionListener;
import mirrormonkey.util.netevent.server.tools.MockHostedConnection;
import mirrormonkey.util.netevent.server.tools.MockServer;
import mirrormonkey.util.netevent.server.tools.MockConnectionListener.HostedConnectionEvent;

import org.junit.After;
import org.junit.BeforeClass;
import org.junit.Test;

import com.jme3.network.ConnectionListener;

/**
 * Integration test: For the whole package <tt>mirrormonkey.util.netevent</tt>,
 * test if hosted connection connects and disconnects are processed and relayed
 * correctly by the framework.
 * 
 * @author Philipp Christian Loewner
 * 
 */
public class ConnectionEventTest {

	private static final HostedConnectionEvent[] NO_EVENTS = {};

	private static MockServer server;

	private static ServerEventManager manager;

	private static ConnectionEventCreator creator;

	private static MockConnectionListener[] listeners;

	private static HostedConnectionEvent[] events;

	@BeforeClass
	public static void setUpClass() {
		server = new MockServer();

		manager = new ServerEventManager();

		creator = manager.getConnectionListener();
		server.addConnectionListener(creator);

		listeners = new MockConnectionListener[] {
				new MockConnectionListener(), new MockConnectionListener() };

		events = new HostedConnectionEvent[] {
				new HostedConnectionEvent(server, new MockHostedConnection()),
				new HostedConnectionEvent(server, new MockHostedConnection()) };
	}

	@After
	public void tearDown() {
		MockConnectionListener.reset(listeners);
	}

	public void addAll(HostedConnectionEvent[] events) {
		for (HostedConnectionEvent e : events) {
			creator.connectionAdded(e.server, e.connection);
		}
	}

	public void removeAll(HostedConnectionEvent[] events) {
		for (HostedConnectionEvent e : events) {
			creator.connectionRemoved(e.server, e.connection);
		}
	}

	public void checkEvents(HostedConnectionEvent[] added,
			HostedConnectionEvent[] removed) {
		MockConnectionListener.checkAdded(listeners, added);
		MockConnectionListener.checkRemoved(listeners, removed);
	}

	/**
	 * Tests if connectionAdded calls are relayed correctly
	 */
	@Test
	public void testAddEvent() {
		for (ConnectionListener l : listeners) {
			manager.addConnectionListener(l);
		}
		addAll(events);

		checkEvents(NO_EVENTS, NO_EVENTS);

		manager.processEvents();
		checkEvents(events, NO_EVENTS);
	}

	/**
	 * Tests if connectionRemoved calls are relayed properly
	 */
	@Test
	public void testRemoveEvent() {
		removeAll(events);
		checkEvents(NO_EVENTS, NO_EVENTS);

		manager.processEvents();
		checkEvents(NO_EVENTS, events);
	}

	/**
	 * Tests if removing listeners stops exactly their notification
	 */
	@Test
	public void testListenerRemone() {
		manager.removeConnectionListener(listeners[0]);
		creator.connectionAdded(events[0].server, events[0].connection);
		manager.processEvents();

		listeners[0].checkAdded(NO_EVENTS);
		listeners[1].checkAdded(new HostedConnectionEvent[] { events[0] });
	}

}
